unit c_list;
//Класс списка указателей
//Из-за того что FPC не позволяет использовать шаблоны, выкручиваться приходится
//именно таким способом

interface

type

  TList = class
  protected
    FCount: Integer;
    FItems: array of Pointer;
    procedure PutItem(Ind: Integer; Item: Pointer);
    function Get(Index: Integer): Pointer; virtual;
  public
    constructor Create;
    destructor Destroy; override;
    function Add(Item: Pointer): Integer; virtual;
    procedure Del(Ind: Integer);
    procedure Swap(Ind1: Integer; Ind2: Integer);
    procedure Insert(Ind: Integer; const Item: Pointer);
    procedure Clean;
    property Items[Index: Integer]: Pointer read Get write PutItem;
    property Count: Integer read FCount;
  end;

implementation

constructor TList.Create;
begin
  inherited;
  FCount := 0;
end;

destructor TList.Destroy;
begin
  Clean;
  inherited;
end;

function TList.Add(Item: Pointer): Integer;
begin
  Result := 0;
  SetLength(FItems, FCount + 1);
  FItems[FCount] := Item;
  Result := FCount;
  Inc(FCount);
end;

procedure TList.Del(Ind: Integer);
var
  i: Integer;
begin
  for i := Ind to FCount - 2 do
    FItems[i] := FItems[i + 1];
  SetLength(FItems, FCount - 1);
  Dec(FCount);
end;

function TList.Get(Index: Integer): Pointer;
begin
  Result := FItems[Index];
end;

procedure TList.PutItem(Ind: Integer; Item: Pointer);
begin
  if Ind < FCount then
    FItems[Ind] := Item;
end;

procedure TList.Swap(Ind1: Integer; Ind2: Integer);
var
  tT: Pointer;
begin
  tT := Items[Ind1];
  Items[Ind1] := Items[Ind2];
  Items[Ind2] := tT;
end;

procedure TList.Insert(Ind: Integer; const Item: Pointer);
var
  i: Integer;
begin
  //Если массив пуст, то индекс не важен - просто вставляем
  if (FCount = 0) or (Ind > FCount) then
  begin
    Add(Item);
    Exit;
  end;

  Inc(FCount);
  SetLength(FItems, FCount);

  for i := High(FItems) downto Ind + 1 do
    FItems[i] := FItems[i - 1];
  FItems[Ind] := Item;
end;

procedure TList.Clean;
begin
  SetLength(FItems, 0);
end;

end.
